package com.example.demo;

import com.example.demo.util.CommonThread;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.omg.PortableInterceptor.INACTIVE;

import javax.swing.*;
import java.sql.*;
import java.util.*;

/**
 * *  Author:zlf
 * *  2020/10/10 9:55
 **/
public class MyTestClass {
    public void go() {
        System.out.println("gogo");
    }

    public static long concurrentTime1, concurrentTime2, concurrentMemory1, concurrentMemory2;

    @BeforeEach
    public void before() {
        //得到程序开始时的系统时间（纳秒级，最终转化毫秒，保留小数点后两位）
        concurrentTime1 = System.nanoTime();
        //得到虚拟机运行、程序开始执行时jvm所占用的内存。
        Runtime runtime = Runtime.getRuntime();
        concurrentMemory1 = runtime.totalMemory() - runtime.freeMemory();
    }

    @AfterEach
    public void after() {
        //得到程序执行完毕时的系统时间（毫秒级）
        concurrentTime2 = System.nanoTime();
        //得到虚拟机运行、所要测试的执行代码执行完毕时jvm所占用的内存（byte）。
        Runtime runtime = Runtime.getRuntime();
        concurrentMemory2 = runtime.totalMemory() - runtime.freeMemory();

        //计算start和end之间的代码执行期间所耗时间(ms)与内存(M)。
        // 1毫秒(ms) = 1000微秒(us) = 1000 000纳秒(ns)
        // 1M = 1*2^20 byte = 1024 * 1024 byte;
        String time = String.valueOf((double) (concurrentTime2 - concurrentTime1) / 1000000);
        String memory = String.valueOf((double) (concurrentMemory2 - concurrentMemory1) / 1024 / 1024);
        System.out.println("---------------您的代码执行时间为：" + time.substring(0, time.equals("0.0") ? 1 : (time.indexOf(".") + 3)) + " ms, 消耗内存：" + memory.substring(0, memory.equals("0.0") ? 1 : (memory.indexOf(".") + 3)) + " M + !---------------");
    }

    @Test
    public void no1() {
        try {

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test() {
        try {
            StaticTest st1 = new StaticTest();
            st1.gogo();

            if (st1.a == -1) {

            }
            System.out.println("sss");
        } catch (Exception e) {
            e.printStackTrace();
        }


        StaticTest st2 = new StaticTest();
        st2.gogo();

    }

    /**
     * 失败，占用内存太高
     * 扔 n 个骰子，向上面的数字之和为 S。给定 n，请列出所有可能的 S 值及其相应的概率。
     * <p>
     * 样例
     * 样例 1：
     * <p>
     * 输入：n = 1
     * 输出：[[1, 0.17], [2, 0.17], [3, 0.17], [4, 0.17], [5, 0.17], [6, 0.17]]
     * 解释：掷一次骰子，向上的数字和可能为1,2,3,4,5,6，出现的概率均为 0.17。
     * 样例 2：
     * <p>
     * 输入：n = 2
     * 输出：[[2,0.03],[3,0.06],[4,0.08],[5,0.11],[6,0.14],[7,0.17],[8,0.14],[9,0.11],[10,0.08],[11,0.06],[12,0.03]]
     * 解释：掷两次骰子，向上的数字和可能在[2,12]，出现的概率是不同的。
     */
    public List<Map.Entry<Integer, Double>> dicesSum(int n) {
        // Write your code here
        // Ps. new AbstractMap.SimpleEntry<Integer, Double>(sum, pro)
        // to create the pair
        Map<Integer, Double> mapResult = new HashMap<>();
        //组装所有骰子
        int[] Dice = {1, 2, 3, 4, 5, 6};
        Map<Integer, Integer> map = new HashMap();

        dicesSumChild(Dice, n, 0, map);

        int total = (int) map.values().stream().mapToInt((x) -> x).summaryStatistics().getSum();
        map.entrySet().forEach(c -> {
            mapResult.put(c.getKey(), c.getValue() * 1.0 / total);
        });
        List<Map.Entry<Integer, Double>> listResult = new ArrayList<>();
        listResult.addAll(mapResult.entrySet());
        return listResult;
    }

    private void dicesSumChild(int[] Dice, int n, int num, Map<Integer, Integer> map) {
        n--;
        for (int a : Dice) {
            if (n == 0) {
                int key = a + num;
                if (map.containsKey(key))
                    map.put(key, map.get(key) + 1);
                else {
                    map.put(key, 1);
                }
                continue;
            } else {
                dicesSumChild(Dice, n, a + num, map);
            }
        }
    }


    /*
     * https://www.lintcode.com/problem/inner-product/description
     * Given an array A with size N and array B with size K.
     * You can choose K numbers from array A with the following rules:
     * 1、 Each A[i] can only be selected once.
     * 2、 if i==1 or i==N ,A[i] can be selected directly.
     * 3、 if 2<=i<=N-1 ,and A[i-1] or A[i+1] has been selected, A[i] can be selected.
     * 4、 You should select exactly K numbers.
     * In other words that you can select one element from the leftmost or rightmost of the AA array, selected element will be remove，
     * Then use the elements to create an array C in order of your selection.
     * You are asked to find the maximun inner product of B and C.
     * @param A: the A array
     * @param B: the B array
     * @return: return the maxium inner product of B and C
     */
    public long getMaxInnerProduct(int[] A, int[] B) {
        // write your code here
        if (A.length < B.length) {
            return -1L;
        }
        int[] C = new int[B.length];

        List<String> list = getBinaryCombination(B.length);

        long maxNum = 0;

        for (String s : list) {
            int j = A.length - 1;
            int z = 0;
            for (int i = 0; i < B.length; i++) {
                if (s.charAt(i) == '1') {
                    C[i] = A[j];
                    j--;
                } else {
                    C[i] = A[z];
                    z++;
                }
            }
            long tempNum = getInnerProduct(B, C);
            if (tempNum > maxNum) {
                maxNum = tempNum;
            }
        }
        System.out.println(maxNum);
        return maxNum;
    }

    private long getInnerProduct(int[] A, int[] B) {
        long result = 0;
        if (A.length != B.length) {
            return result;
        }
        for (int i = 0; i < A.length; i++) {
            result += (A[i] * B[i]);
        }
        return result;
    }

    /**
     * 用0和1组成 N位数，求出所有组合
     *
     * @param digits 位数
     * @return
     */
    public void getCombination(int digits) {
        int[] condition = {0, 1};
        List<Integer> list = new ArrayList<>();
        for (int i : condition) {
            list.add(i);
            recursion(list, condition, digits);
        }
    }

    private List<Object[]> listAll = new ArrayList<>();

    private void recursion(List<Integer> list, int[] condition, int digits) {
        digits--;
        if (digits == 0) {
            listAll.add(list.toArray());
            list.remove(list.size() - 1);
            return;
        }
        for (int i : condition) {
            list.add(i);
            recursion(list, condition, digits);
        }
        list.remove(list.size() - 1);
    }

    //获取 0和1 组成digits位的 所有排列组合
    private List<String> getBinaryCombination(int digits) {
        List<String> list = new ArrayList<>();

        StringBuilder zeroStr = new StringBuilder();
        for (int i = 0; i < digits; i++) {
            zeroStr.append("0");
        }
        for (int i = 0; i < Math.pow(2, digits); i++) {
            String s = Integer.toBinaryString(i);
            list.add((zeroStr.toString() + s).substring(zeroStr.length() + s.length() - digits));
        }
        return list;
    }

    public static int count = 0;

    @Test
    public void SynchronizedTest() {
        new CommonThread() {
            @Override
            public void run() {
                for (int i = 0; i < 10000; i++)
                    synchronized (MyTestClass.class) {
                        count++;
                    }
            }
        }.start();

        System.out.println(count);
    }

    @Test
    public void TestString() {
        String a = "123";
        String b = "123";
        System.out.println(a == b);
    }

    // MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://10.179.201.161:3308/api_order";

    @Test
    public void TestDbUtil() {
        Connection conn = null;
        Statement stmt = null;
        try {
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);

            // 打开链接
            System.out.println("连接数据库...");
            conn = DriverManager.getConnection(DB_URL, "root", "SUNBOX@tbd7");

            // 执行查询
            System.out.println(" 实例化Statement对象...");
            stmt = conn.createStatement();
            String sql;
            sql = "select ope_time as '加油时间',oil_code as '油品品号',oil_liter as '加油升数',amount as '加油金额'," +
                    " station_no as '消费站点' from snpc_ord_refuel where user_id = '33579138' ";
            ResultSet rs = stmt.executeQuery(sql);

            // 展开结果集数据库
            while (rs.next()) {

                // 通过字段检索
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String url = rs.getString("url");

                // 输出数据
                System.out.print("ID: " + id);
                System.out.print(", 站点名称: " + name);
                System.out.print(", 站点 URL: " + url);
                System.out.print("\n");
            }
            // 完成后关闭
            rs.close();
            stmt.close();
            conn.close();
        } catch (SQLException se) {
            // 处理 JDBC 错误
            se.printStackTrace();
        } catch (Exception e) {
            // 处理 Class.forName 错误
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException se2) {
            }// 什么都不做
            try {
                if (conn != null) conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
        System.out.println("Goodbye!");
    }

    @Test
    public void dealPhone() {
        List<String> list = new ArrayList<String>() {
            {
                add("13165583921");
            }
        };
    }

    public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
        int num = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for (int i : A) {
            for (int j : B) {
                map.put(i + j, map.getOrDefault(i + j, 0) + 1);
            }
        }
        for (int k : C) {
            for (int l : D) {
                if (map.containsKey(-k - l)) {
                    num += map.get(k + l);
                }
            }
        }
        return num;

    }

    @Test
    public void testsss() {
        TreeNode root = new TreeNode(3);

        TreeNode left = new TreeNode(9);
        TreeNode right = new TreeNode(20);
        root.left = left;
        root.right = right;
        TreeNode leftLeft = new TreeNode(4);
        TreeNode leftRight = new TreeNode(20);
        left.left = leftLeft;
        left.right = leftRight;

        TreeNode rightLeft = new TreeNode(15);
        TreeNode rightRight = new TreeNode(7);
        right.left = rightLeft;
        right.right = rightRight;

        List<List<Integer>> lists = zigzagLevelOrder11(root);

        int a = 3;
    }

    public int reversePairs(int[] nums) {
        int num = 0;
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                long temp = nums[j];
                if (nums[i] > temp * 2) {
                    num++;
                }
            }
        }
        return num;
    }

    public List<List<Integer>> zigzagLevelOrder11(TreeNode root) {
        List<List<Integer>> lists = new ArrayList<>();
        if (root == null) {
            return lists;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean beginLeft = true;
        while (!queue.isEmpty()) {
            Deque<Integer> levelList = new LinkedList<Integer>();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode treeNode = queue.poll();

                if (beginLeft) {
                    levelList.addLast(treeNode.val);
                } else {
                    levelList.addFirst(treeNode.val);
                }
                if (treeNode.left != null) {
                    queue.offer(treeNode.left);
                }
                if (treeNode.right != null) {
                    queue.offer(treeNode.right);
                }
            }
            lists.add(new LinkedList<Integer>(levelList));
            beginLeft = !beginLeft;
        }
        return lists;
    }


    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> ans = new LinkedList<List<Integer>>();
        if (root == null) {
            return ans;
        }

        Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
        nodeQueue.offer(root);
        boolean isOrderLeft = true;

        while (!nodeQueue.isEmpty()) {
            Deque<Integer> levelList = new LinkedList<Integer>();
            int size = nodeQueue.size();
            for (int i = 0; i < size; ++i) {
                TreeNode curNode = nodeQueue.poll();
                if (isOrderLeft) {
                    levelList.offerLast(curNode.val);
                } else {
                    levelList.offerFirst(curNode.val);
                }
                if (curNode.left != null) {
                    nodeQueue.offer(curNode.left);
                }
                if (curNode.right != null) {
                    nodeQueue.offer(curNode.right);
                }
            }
            ans.add(new LinkedList<Integer>(levelList));
            isOrderLeft = !isOrderLeft;
        }

        return ans;
    }

    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }
}
